package com.shell.customer.base.service.impl;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.entity.auth.AuthOrgan;
import com.shell.bee.entity.auth.AuthRole;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.esign.vo.EsignAuthResponse;
import com.shell.bee.file.utils.FileHelper;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.customer.base.CusInfoModifyEvent;
import com.shell.customer.base.dao.CusInfoModifyDao;
import com.shell.customer.base.rx.SaveCusAcctSubscriber;
import com.shell.customer.base.rx.SaveCusInfoAprvSubscriber;
import com.shell.customer.base.service.BankAcctModifyService;
import com.shell.customer.base.service.CusAcctService;
import com.shell.customer.base.service.CusAcctUseService;
import com.shell.customer.base.service.CusRecService;
import com.shell.customer.base.service.CusTagService;
import com.shell.customer.base.vo.CusAcctVo;
import com.shell.customer.cfca.service.CfcaAuthTxService;
import com.shell.customer.esign.service.EsignAuthTxService;
import com.shell.customer.group.service.CusGrpService;
import com.shell.customer.po.CusAcct;
import com.shell.customer.po.CusAcctUse;
import com.shell.customer.po.CusInfoAprv;
import com.shell.customer.po.CusRec;
import com.shell.customer.trade.service.CustomerAcctService;
import com.shell.customer.util.CustomerUtil;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.MessageSender;
import com.shell.governor.modules.message.keyword.CusModifyKeyword;
import java.math.BigDecimal;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service("bankAcctService")
public class BankAcctModifyServiceImpl implements BankAcctModifyService {
	@Autowired
	private CusInfoModifyDao infoModifyDao;
	@Autowired
	private CusAcctService cusAcctService;
	@Autowired
	private SaveCusInfoAprvSubscriber saveCusInfoAprvSubscriber;
	@Autowired
	private SaveCusAcctSubscriber saveCusAcctSubscriber;
	@Autowired
	private CustomerAcctService customerAcctService;
	@Autowired
	private CusRecService customerService;
	@Autowired
	private CusAcctUseService cusAcctUseService;
	@Autowired
	private CusGrpService cusGrpService;
	@Autowired
	private EsignAuthTxService esignAuthTxService;
	@Autowired
	private CusTagService cusTagService;
	@Autowired
	private CfcaAuthTxService cfcaAuthTxService;

	private boolean hasRole(List<AuthRole> roles, String roleCodes) {
		boolean rs = false;
		for (AuthRole role : roles) {
			if (roleCodes.indexOf(role.getRoleCode()) != -1) {
				rs = true;
				break;
			}
		}
		return rs;
	}

	public List<CusAcctVo> getAccts() {
		AuthOrgan organ = CommonDataUtil.getCurEnt();
		String cusId = organ.getOrganId();
		List<AuthRole> roles = CommonDataUtil.getCurUserRoles();
		boolean isAdmin = false;

		String acctState = "";
		String[] roleCodes = { "ENT_ADMIN", "PERSONAL", "SELF_EMPLOYED" };
		if (hasRole(roles, String.join(",", roleCodes))) {
			isAdmin = true;
		}
		if (!isAdmin) {
			acctState = "N";
		}
		return this.infoModifyDao.getAccts(cusId, acctState);
	}

	public void addAcct(CusAcctVo acctVo) {
		AuthOrgan organ = CommonDataUtil.getCurEnt();
		String cusId = organ.getOrganId();
		if (StringUtil.empty(acctVo.getCusId())) {
			acctVo.setCusId(cusId);
		}
		if (StringUtil.empty(acctVo.getAcctId())) {
			acctVo.setAcctId(SystemUtil.getUUID());
		}
		if (StringUtil.empty(acctVo.getAcctType())) {
			acctVo.setAcctType("0");
		}
		CusInfoModifyEvent<CusAcct> acctEvent = new CusInfoModifyEvent();
		Observable<CusInfoModifyEvent<CusAcct>> observers = Observable.just(acctEvent);
		CusRec cusRec = (CusRec) this.customerService.selectByKey(cusId);
		if ((!"FINNER".equals(organ.getCusType())) && (!this.cusTagService.hasTag(cusId, null, "OPERATOR"))
				&& (!this.cusTagService.hasTag(cusId, null, "FOCAL_CO"))) {
			if (CustomerUtil.onEsign()) {
				applyEsignBankAuthInfo(acctVo, cusRec);
				acctVo.setAcctState("V");
			} else {
				CusInfoAprv acctAprv = new CusInfoAprv();
				acctVo.setAcctState("R");
				acctAprv.setAprvId(SystemUtil.getUUID());
				acctAprv.setBusinessId(acctVo.getAcctId());
				acctAprv.setApprover(cusRec.getGrpId());
				acctAprv.setApplyer(CommonDataUtil.getUserName());
				acctAprv.setCreateTime(DateUtil.getSystemDateTime());
				acctAprv.setOperator(CommonDataUtil.getUserId());
				acctEvent.setAprv(acctAprv);
				observers.subscribe(this.saveCusInfoAprvSubscriber);

				sendFirstTrialMsg(acctVo.getAcctNo(), acctAprv);
			}
		} else {
			acctVo.setAcctState("N");

			CusAcct acct = new CusAcct();
			BeanUtils.copyProperties(acctVo, acct);
			pushAcct(acct);
		}
		acctEvent.setT(acctVo);
		observers.subscribe(this.saveCusAcctSubscriber);

		FileHelper.setRelateId(acctVo.getBankCertificateFile(), cusId, "3");
	}

	private void applyCfcaBankAuthInfo(CusAcctVo acctVo, CusRec cusRec) {
		CusAcct acct = new CusAcct();
		BeanUtils.copyProperties(acctVo, acct);
		String msg = null;
		try {
			msg = this.cfcaAuthTxService.authEntPayApply(cusRec.getCusId(), acct);
		} catch (Exception e) {
			msg = "��������������CFCA��" + e.getMessage();
		}
		if (msg != null) {
			throw new UnCheckMsgException(msg);
		}
	}

	private void applyEsignBankAuthInfo(CusAcctVo acctVo, CusRec cusRec) {
		CusAcct acct = new CusAcct();
		BeanUtils.copyProperties(acctVo, acct);
		String msg = null;
		try {
			EsignAuthResponse response = this.esignAuthTxService.authBaseInfo(cusRec);
			if (response.getErrCode() != 0) {
				throw new UnCheckMsgException("������������������" + response.getMsg());
			}
			response = this.esignAuthTxService.toPay(acct, response.getServiceId());
			if (response.getErrCode() != 0) {
				msg = response.getMsg();
			}
		} catch (Exception e) {
			msg = e.getMessage();
			e.printStackTrace();
		}
		if (msg != null) {
			throw new UnCheckMsgException("������������������" + msg);
		}
	}

	private void sendFirstTrialMsg(String acctNo, CusInfoAprv acctAprv) {
		String template = "MT06000";
		CusModifyKeyword keyWord = new CusModifyKeyword();
		keyWord.setApplyDate(DateUtil.parseDate(acctAprv.getCreateTime(), "yyyyMMdd", "yyyy-MM-dd"));
		keyWord.setCusName(CommonDataUtil.getCurEntName());
		keyWord.setAcctNo(acctNo);
		String senderId = CommonDataUtil.getUserId();

		String aprvCusId = this.cusGrpService.findGroupEnt(acctAprv.getApprover(), "GROUP_FIRST_TRIAL");
		MessageSender.sendMessageByTmpl(senderId, template, keyWord, aprvCusId);
	}

	@Pagination
	public List<CusAcctVo> getAprvAccts(PageLimit limit, CusAcctVo acctVo) {
		acctVo.setCusName(StringUtil.getParameterLike(acctVo.getCusName()));
		return this.infoModifyDao.getAprvAccts(acctVo);
	}

	private void aprv(CusAcct acct, CusInfoAprv aprv) {
		CusInfoAprv acctAprv = new CusInfoAprv();
		acctAprv.setAprvId(SystemUtil.getUUID());
		acctAprv.setBusinessId(acct.getAcctId());
		acctAprv.setApprover(aprv.getApprover());
		acctAprv.setApplyer(aprv.getApplyer());
		acctAprv.setAprvRs(aprv.getAprvRs());
		acctAprv.setCreateTime(DateUtil.getSystemDateTime());
		acctAprv.setAprvRemark(aprv.getAprvRemark());

		CusInfoModifyEvent<CusAcct> acctEvent = new CusInfoModifyEvent();
		Observable<CusInfoModifyEvent<CusAcct>> observers = Observable.just(acctEvent);

		acctEvent.setT(acct);
		observers.subscribe(this.saveCusAcctSubscriber);
		acctEvent.setAprv(acctAprv);
		observers.subscribe(this.saveCusInfoAprvSubscriber);
	}

	public void trialReject(CusInfoAprv acctAprv) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(acctAprv.getBusinessId());
		acct.setAcctState("I");
		acctAprv.setOperator(CommonDataUtil.getUserId());
		aprv(acct, acctAprv);

		CusModifyKeyword keyWord = new CusModifyKeyword();
		keyWord.setApplyDate(DateUtil.getSystemDate());
		keyWord.setAcctNo(acct.getAcctNo());
		keyWord.setOperator(CommonDataUtil.getUserName());
		keyWord.setRemark(acctAprv.getAprvRemark());
		keyWord.setBankName(acct.getBankName());
		String url = SpringContextUtil.getProperty("customer.website");
		if (StringUtil.notEmpty(url)) {
			keyWord.setUrl(url);
		}
		String senderId = CommonDataUtil.getUserId();

		MessageSender.sendMessageByTmpl(senderId, "MT06001", keyWord, acct.getCusId());
		MessageSender.sendMessageByTmpl(senderId, "MT06013", keyWord, acct.getCusId());
	}

	public void trialPass(CusInfoAprv aprv) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(aprv.getBusinessId());
		CusRec rec = (CusRec) this.customerService.selectByKey(acct.getCusId());
		acct.setAcctState("E");
		aprv.setOperator(CommonDataUtil.getUserId());
		aprv(acct, aprv);

		String template = "MT06002";
		CusModifyKeyword keyWord = new CusModifyKeyword();

		keyWord.setApplyDate(DateUtil.getSystemDate());
		keyWord.setAcctNo(acct.getAcctNo());
		keyWord.setOperator(CommonDataUtil.getUserName());
		keyWord.setCusName(rec.getCusName());

		String senderId = CommonDataUtil.getUserId();

		String aprvCusId = this.cusGrpService.findGroupEnt(aprv.getApprover(), "GROUP_LAST_TRIAL");
		MessageSender.sendMessageByTmpl(senderId, template, keyWord, aprvCusId);
	}

	public void finalPass(CusInfoAprv aprv) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(aprv.getBusinessId());
		acct.setAcctState("N");
		aprv.setOperator(CommonDataUtil.getUserId());
		aprv(acct, aprv);

		CusModifyKeyword keyWord = new CusModifyKeyword();
		keyWord.setApplyDate(DateUtil.getSystemDate());
		keyWord.setAcctNo(acct.getAcctNo());
		keyWord.setBankName(acct.getBankName());
		String senderId = CommonDataUtil.getUserId();

		MessageSender.sendMessageByTmpl(senderId, "MT06003", keyWord, acct.getCusId());
		MessageSender.sendMessageByTmpl(senderId, "MT06012", keyWord, acct.getCusId());

		pushAcct(acct);
	}

	public void finalReject(CusInfoAprv aprv) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(aprv.getBusinessId());
		acct.setAcctState("R");
		CusRec rec = (CusRec) this.customerService.selectByKey(acct.getCusId());
		aprv.setOperator(CommonDataUtil.getUserId());
		aprv(acct, aprv);

		String template = "MT06004";
		CusModifyKeyword keyWord = new CusModifyKeyword();

		keyWord.setApplyDate(DateUtil.getSystemDate());
		keyWord.setAcctNo(acct.getAcctNo());
		keyWord.setCusName(rec.getCusName());
		keyWord.setOperator(CommonDataUtil.getUserName());
		keyWord.setRemark(aprv.getAprvRemark());

		String senderId = CommonDataUtil.getUserId();

		String aprvCusId = this.cusGrpService.findGroupEnt(aprv.getApprover(), "GROUP_FIRST_TRIAL");

		MessageSender.sendMessageByTmpl(senderId, template, keyWord, aprvCusId);
	}

	private void pushAcct(CusAcct acct) {
		CusRec cusRec = (CusRec) this.customerService.selectByKey(acct.getCusId());

		this.customerAcctService.addCard(acct, cusRec, null);
	}

	public void setInvalid(String acctId) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(acctId);
		CusRec cusRec = (CusRec) this.customerService.selectByKey(acct.getCusId());
		acct.setAcctState("I");
		this.cusAcctService.saveOrUpdate(acct);

		CusAcctUse acctUse = new CusAcctUse();
		acctUse.setAcctNo(acct.getAcctNo());
		this.cusAcctUseService.deleteEntity(acctUse);
		this.customerAcctService.addCard(acct, cusRec, null);
	}

	public void setDefault(String acctId) {
		CusAcct acct = (CusAcct) this.cusAcctService.selectByKey(acctId);
		CusRec cusRec = (CusRec) this.customerService.selectByKey(acct.getCusId());

		this.cusAcctUseService.deleteByCusId(acct.getCusId(), "00");

		String[] realAcctUses = { "00" };

		CusAcctUse acctUse = new CusAcctUse();
		acctUse.setAcctNo(acct.getAcctNo());
		acctUse.setUseCode("00");
		this.cusAcctUseService.saveOrUpdate(acctUse);

		this.customerAcctService.delAcctUse(cusRec.getCusId(), "0", "00");
		this.customerAcctService.addCard(acct, cusRec, realAcctUses);
	}

	public RetMsg payAmountAuth(String acctId, BigDecimal amount) {
		String cusId = CommonDataUtil.getCurEntId();
		CusAcct cusAcct = (CusAcct) this.cusAcctService.selectByKey(acctId);
		RetMsg retMsg = null;
		if (CustomerUtil.onEsign()) {
			retMsg = this.esignAuthTxService.payAmountAuth(cusAcct.getAcctNo(), amount);
		}
		if (!"error".equals(retMsg.getType())) {
			CusRec cus = (CusRec) this.customerService.selectByKey(cusId);
			CusInfoAprv acctAprv = new CusInfoAprv();
			acctAprv.setAprvId(SystemUtil.getUUID());
			acctAprv.setBusinessId(cusAcct.getAcctId());
			acctAprv.setApprover(cus.getGrpId());
			acctAprv.setApplyer(CommonDataUtil.getUserName());
			acctAprv.setCreateTime(DateUtil.getSystemDateTime());
			acctAprv.setOperator(CommonDataUtil.getUserId());

			cusAcct.setAcctState("R");
			aprv(cusAcct, acctAprv);

			sendFirstTrialMsg(cusAcct.getAcctNo(), acctAprv);
		}
		return retMsg;
	}
}
